/*
 * IBM Corporation.
 * Copyright (c) 2014 All Rights Reserved.
 */

package com.ibm.iisp.dataie.service;

import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaBuilder.In;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ibm.iisp.auth.service.AuthService;
import com.ibm.iisp.auth.util.SecurityUtils;
import com.ibm.iisp.auth.vo.LoginUser;
import com.ibm.iisp.base.service.BaseService;
import com.ibm.iisp.common.exception.I18nAppException;
import com.ibm.iisp.common.util.FileStoreUtils;
import com.ibm.iisp.common.vo.PagedQueryResult;
import com.ibm.iisp.dataie.dao.DataImportRepository;
import com.ibm.iisp.dataie.model.DataIETable;
import com.ibm.iisp.dataie.model.DataIETemplate;
import com.ibm.iisp.dataie.model.DataImport;
import com.ibm.iisp.dataie.model.DataImport.State;
import com.ibm.iisp.dataie.model.DataImportAction;
import com.ibm.iisp.dataie.model.DataImportNodeTable;
import com.ibm.iisp.dataie.vo.DataExportRequest;
import com.ibm.iisp.dataie.vo.DataImportQueryParam;
import com.ibm.iisp.dataie.vo.NodeImportState;


/**
 * 类作用：
 * 
 * @author Johnny@cn.ibm.com 使用说明：
 */
@Service
@Transactional(readOnly = true)
public class DataIEServiceImpl implements DataIEService {
	/**
	 * 
	 */
	public static final String RES_ID_PREFIX = "DATA_IE_TABLES-";
	/**
	 * 
	 */
	public static final String DATA_IMP_TEMPATE_ROOT = "/iisp-data-ie/tempates";
	public static final String DATA_IMP_FILE_ROOT = "/iisp-data-ie/datafiles";
	public static final String DATA_EXP_FILE_ROOT = FileStoreUtils.TEMP_PATH + "/iisp-data-ie/exports";
	Logger log = LoggerFactory.getLogger(getClass());
	@Inject
	EntityManager dao;
	@Inject
	DataImportRepository dataImportRepository;
	@Inject
	BaseService configService;
	@Inject
	FileStoreUtils fileStoreUtils;
	@Inject
	AuthService authService;
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#getDataIETemplatesByTable(java. lang.String)
	 */
	@Override
	public List<DataIETemplate> getDataIETemplatesByTable(String table) {
		TypedQuery<DataIETemplate> qry = dao.createNamedQuery(DataIETemplate.QUERY_BY_TABLE, DataIETemplate.class)
		    .setParameter("tableName", table);
		return qry.getResultList();
	}

	@Override
	public List<DataIETable> getDataIETables() {
		List<DataIETable> tables = dao.createNamedQuery(DataIETable.QUERY_ALL, DataIETable.class).getResultList();
		tables = authService.filterAuthorizedResource(tables, RES_ID_PREFIX);
		return tables;
	}

	@Override
	public DataExportRequest getDataExportRequestByTemplate(Long templateId) {
		DataIETemplate dataIETemplate = this.getDataIETemplate(templateId);
		String tableName = dataIETemplate.getTabName();
		DataIETable tb = dao.find(DataIETable.class, tableName);
		DataExportRequest vo = new DataExportRequest();
		vo.setTableName(tableName);
		vo.setIsExportIncOnly(tb.getIsExportIncOnly());
		String defaultFilter = tb.getDefaultFilter();
		if (defaultFilter != null) {
			defaultFilter = DataIEUtils.replaceVariables(defaultFilter);
		}
		vo.setFilter(defaultFilter);
		vo.setTemplateId(templateId);
		return vo;

	}

	@Override
	public DataExportRequest getDataExportRequestByName(String tableName, boolean hasTemplate) {
		if (hasTemplate) {
			TypedQuery<DataIETemplate> query = dao.createNamedQuery(DataIETemplate.QUERY_BY_TABLE, DataIETemplate.class)
				.setParameter("tableName", tableName);
			List<DataIETemplate> list = query.getResultList();
			// 有模板就用最新模板，否则生成缺省模板
			if (!list.isEmpty()) {
				return getDataExportRequestByTemplate(list.get(0).getId());
			}
		}
		DataIETable tb = dao.find(DataIETable.class, tableName);
		// DictItem tableConfig = configService.getParamItem(DataImportTemplate.CONFIG_CODE, tableName);
		// Map<String, Object> props = getProperties(tableConfig);
		Set<String> requiredColumns = DataIEUtils.getRequiredColumns(tb);
		int indexOf = tableName.indexOf(".");
		String uTabName = indexOf > 0 ? tableName.substring(indexOf + 1).toUpperCase() : tableName.toUpperCase();
		Query colQuery = dao.createNamedQuery(DataIETemplate.DATA_EXPORT_TABLE_DEF).setParameter(1, uTabName);
		List<?> resultList = colQuery.getResultList();
		List<DataExportRequest.ColumnDef> cols = new ArrayList<>(resultList.size());
		for (Object obj : resultList) {
			Object[] cs = (Object[]) obj;
			DataExportRequest.ColumnDef col = new DataExportRequest.ColumnDef();
			col.setName(((String) cs[0]).toUpperCase());
			col.setDesc((String) cs[1]);

			if (requiredColumns.contains(col.getName())) {
				col.setIsRequired(true);
			}
			col.setIsExport(true);
			cols.add(col);
		}
		DataExportRequest vo = new DataExportRequest();
		vo.setIsExportIncOnly(tb.getIsExportIncOnly());
		vo.setColumns(cols);
		vo.setTableName(tableName);
		String defaultFilter = tb.getDefaultFilter();
		if (defaultFilter != null) {
			defaultFilter = DataIEUtils.replaceVariables(defaultFilter);
		}
		vo.setFilter(defaultFilter);

		return vo;

	}

//	/**
//	 * @param defaultFilter
//	 * @return
//	 */
//	private String replaceVaiables(String defaultFilter) {
//		if (defaultFilter.indexOf("${currentDataDate}") > 0) {
//			String dt = (String) RequestContextHolder.getRequestAttributes().getAttribute("currentDataDate",
//				RequestAttributes.SCOPE_SESSION);
//			defaultFilter = defaultFilter.replace("${currentDataDate}", "'" + dt + "'");
//		}
//		if (defaultFilter.indexOf("${currentNodeCode}") > 0) {
//			String dt = (String) RequestContextHolder.getRequestAttributes().getAttribute("currentNodeCode",
//				RequestAttributes.SCOPE_SESSION);
//			defaultFilter = defaultFilter.replace("${currentNodeCode}", dt);
//		}
//		return defaultFilter;
//	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#getDefaultTemplate(java.lang. String)
	 */
	@Override
	public DataIETemplate genDefaultTemplate(String table) {
		DataIETemplate temp = new DataIETemplate();
		temp.setTabName(table);
		temp.setDscName(table);

		DataExportRequest req = getDataExportRequestByName(table, false);

		DefaultExcelDataExporter exporter = new DefaultExcelDataExporter(req, dao);
		String fn = exporter.init();
		exporter.finish();
		temp.setFileUri(fileStoreUtils.getRelativeFilePath(fn));
		return temp;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#saveTemplate(com.ibm.iisp. dataie.model.DataIETemplate)
	 */
	@Override
	@Transactional(readOnly = false)
	public DataIETemplate saveTemplate(DataIETemplate template) throws I18nAppException {
		String fn = template.getFileUri();
		if (fn != null && fn.indexOf(DATA_IMP_TEMPATE_ROOT) < 0) {// 模板文件换了
			Workbook wb = null;
			FileInputStream is = null;
			try {
				is = new FileInputStream(fn);
				if (fn.endsWith(".xls")) {
					try {
						wb = new HSSFWorkbook(is);
					} catch (OfficeXmlFileException e) {
						log.info("Imported excel 2010 format with xls ext name. will try to use 2010");
						is.close();
						is = null;
					}
				}
				if (wb == null) {
					if (is == null) {
						is = new FileInputStream(fn);
					}
					wb = new XSSFWorkbook(is);
				}

				Sheet sheet = DataIEUtils.getExportDataSheet(wb);
				if (sheet == null) {
					throw new I18nAppException("IISP_DATA_WRONG_SIGNATURE", new String[] { fn }, "模板文件签名错！");
				}

			} catch (IOException e) {
				log.error("Error to open file.", e);
				throw new I18nAppException("IISP_DATA_WRONG_TEMPLATE", new String[] { e.getMessage() }, "非法模板文件");
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					log.error("Error to close file.", e);
				}
			}
			fn = fileStoreUtils.moveFileToDir(fn, DATA_IMP_TEMPATE_ROOT, true, true);
			log.debug("template moved from {} to {}.", fn, fn);
			template.setFileUri(fn);
		}
		if (template.getId() == null) {
			dao.persist(template);
		} else {
			DataIETemplate tmp0 = dao.find(DataIETemplate.class, template.getId());
			tmp0.setDscName(template.getDscName());
			if (fn != null && !fn.equals(tmp0.getFileUri())) {
				fileStoreUtils.removeFile(tmp0.getFileUri());
				tmp0.setFileUri(fn);
			}
		}
		return template;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#getDataIETemplate(java.lang. Long)
	 */
	@Override
	public DataIETemplate getDataIETemplate(Long id) {
		DataIETemplate dtmp = dao.find(DataIETemplate.class, id);
		return dtmp;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#delDataIETemplate(java.lang. Long)
	 */
	@Override
	@Transactional(readOnly = false)
	public void delDataIETemplate(Long id) {
		DataIETemplate tmpl = dao.find(DataIETemplate.class, id);
		dao.remove(tmpl);
		boolean rst = tmpl.getFileUri() != null && fileStoreUtils.removeFile(tmpl.getFileUri());
		if (rst) {
			log.info("File [{}] has beean deleted", tmpl.getFileUri());
		} else {
			log.info("File [{}] not found", tmpl.getFileUri());
		}
	}

	@Override
	@Transactional(readOnly = false)
	public DataImport updateDataImport(DataImport dataImport) {

		return dao.merge(dataImport);
	}

	@Override
	public DataImport getDataImport(Long id) {
		DataImport di = dao.find(DataImport.class, id);
		if (di != null) {
			di.getActions().size();
		}
		return di;
	}

	@Override
	@Transactional(readOnly = false)
	public DataImport dataImportRequest(DataImport dataImport, boolean approved) throws I18nAppException {
		String fn = fileStoreUtils.moveFileToDir(dataImport.getFileUri(), DATA_IMP_FILE_ROOT, true, true);
		log.debug("Import data file moved from {} to {}.", dataImport.getFileUri(), fn);

		dataImport.setFileUri(fn);
		dao.persist(dataImport);
		dao.flush();
		if (approved) {
			DataImportAction action = new DataImportAction();
			action.setAction(DataImportAction.Action.IMPORT);
			action.setMessage("Imported immediately.");
			doDataImport(action, dataImport, null);
		} else {
			DataImportAction action = new DataImportAction();
			action.setAction(DataImportAction.Action.REQUEST);
			doDataImport(action, dataImport, "_tmp");
			action.setMessage(dataImport.getMemo());
			dataImport.setImportState(DataImport.State.DRAFT);
			if (dataImport.getDiscardCount() > 0) {
				dataImport.setMemo("导入数据出错，请下载数据文件查看详情");
				dataImport.setImportState(DataImport.State.ERROR);
			}
			// List<DataImportAction> actions = new ArrayList<>();
			// actions.add(action);
			// dataImport.setActions(actions);
		}
		LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
		dataImport.setNodeCode(loginUser.getPrimaryOrg().getCode());
		dataImport.setNodeName(loginUser.getPrimaryOrg().getName());
		dao.flush();
		return dataImport;
	}

	@Override
	@Transactional(readOnly = false)
	public DataImport dataImportExecute(Long id, DataImportAction action) throws I18nAppException {
		DataImport dataImport = dao.find(DataImport.class, id);
		return doDataImport(action, dataImport, null);
	}

	/**
	 * @param action
	 * @param dataImport
	 * @return
	 * @throws I18nAppException
	 */
	protected DataImport doDataImport(DataImportAction action, DataImport dataImport, String temp) throws I18nAppException {
		if (DataImportAction.Action.APPROVE == action.getAction() || DataImportAction.Action.IMPORT == action.getAction()) {
			if (dataImport.getImportState() != State.DRAFT) {
				throw new I18nAppException("IISP_DATA_IMP_ALREADY_IMPED", null, null);
			}
		}
		if (DataImportAction.Action.APPROVE == action.getAction() || DataImportAction.Action.IMPORT == action.getAction()
			|| DataImportAction.Action.REQUEST == action.getAction()) {
			try {
				ExcelDataImporter importer = new ExcelDataImporter(fileStoreUtils, dao);
				Map<String, Object> colValMap = importer.importDataFile(dataImport, temp);
				if (dataImport.getTableName() == null) {
					throw new I18nAppException("IISP_DATA_WRONG_SIGNATURE", new String[] { dataImport.getFileUri() }, "模板文件签名错！");
				}
				dataImport.setImportState(DataImport.State.IMPORTED);
				String message = "Data Imported";
				action.setMessage(message);
				dataImport.setImportMessage(message);
				DataIETable tb = dao.find(DataIETable.class, dataImport.getTableName());
				dataImport.setTableDesc(tb.getName());
				String proc = temp == null ? tb.getImpProcedure() : tb.getValidProcedure();
				if (proc != null) {
					String procState = DataIEUtils.replaceVariables(colValMap, proc);
					dao.createNativeQuery("{ call " + procState + "}").executeUpdate();
				}
			} catch (I18nAppException e) {
				log.error("Import error!", e);
				throw e;
			} catch (Exception e) {
				log.error("Import error!", e);
				dataImport.setImportState(DataImport.State.ERROR);
				String message = getUnderlyingDBMessage(e);

				throw new I18nAppException("IISP_DATA_IMP_ERROR", new String[] { message }, message);
				// action.setMessage(message);
				//dataImport.setImportMessage(message);
			}
		} else if (DataImportAction.Action.REJECT == action.getAction()) {
			if (dataImport.getImportState() != State.DRAFT) {
				throw new I18nAppException("IISP_DATA_IMP_ALREADY_IMPED", null, null);
			}
			dataImport.setImportState(DataImport.State.REJECTED);
			dataImport.setImportMessage(action.getMessage());
		} else if (DataImportAction.Action.ERROR == action.getAction()) {
			dataImport.setImportState(DataImport.State.ERROR);
			dataImport.setImportMessage(action.getMessage());
		}
		if (dataImport.getActions() == null) {
			dataImport.setActions(new ArrayList<DataImportAction>(1));
		}
		dataImport.getActions().add(action);
		return dataImport;
	}

	String getUnderlyingDBMessage(Exception e) {
		Throwable cause = e;
		while (!(cause instanceof SQLException)) {
			if (cause.getCause() == null) {
				break;
			}
			cause = cause.getCause();
		}
		String message = cause.getMessage();
		return message;
	}

	void verifyDataFile(DataImport dataImport, Workbook wb) throws I18nAppException {
		// 获得第一个工作表对象
		Sheet sheet = DataIEUtils.getExportDataSheet(wb);

		if (sheet == null) {
			throw new I18nAppException("IISP_DATA_WRONG_SIGNATURE", new String[] { dataImport.getFileUri() }, "模板文件签名错！");
		}
		// 得到第一列第一行的单元格
		Row row1 = sheet.getRow(0);
		String table = row1.getCell(0).getStringCellValue();
		dataImport.setTableName(table);
		log.debug("import Table {}...", table);

		DataIETable tb = dao.find(DataIETable.class, table);
		dataImport.setTableDesc(tb.getName());
		Set<String> requiredColumns = DataIEUtils.getRequiredColumns(tb);
		int ttColCount = sheet.getRow(1).getLastCellNum();
		for (int colCount = 0; colCount < ttColCount; colCount++) {
			Cell cell = sheet.getRow(1).getCell(colCount);
			if (cell == null) {
				break;
			}
			requiredColumns.remove(cell.getStringCellValue().toUpperCase());
		}
		if (!requiredColumns.isEmpty()) {
			log.error("模板文件错，必须的字段缺失{}！", requiredColumns);
			String cols = requiredColumns.toString();
			throw new I18nAppException("IISP_MISS_REQUIRED_COLUMNS", new String[] { cols }, "必须的字段缺失:" + cols);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#getDataImports()
	 */
	@Override
	public PagedQueryResult<DataImport> searchDataImports(DataImportQueryParam queryParam) {
		List<DataIETable> tables = dao.createNamedQuery(DataIETable.QUERY_ALL, DataIETable.class).getResultList();
		int allSize = tables.size();
		tables = authService.filterAuthorizedResource(tables, RES_ID_PREFIX);
		final boolean needFilterTable = allSize > tables.size();
		ArrayList<String> tnames = new ArrayList<>(tables.size());
		for (DataIETable dt : tables) {
			tnames.add(dt.getCode());
		}
		if (tnames.isEmpty()) {
			PagedQueryResult<DataImport> result = new PagedQueryResult<>();
			result.setDatas(new ArrayList<DataImport>());
			result.setPageCount(0);
			result.setRecordCount(0);
			return result;
		}
		Specification<DataImport> specification = (logRoot, logCtQuery, cb) -> {
//		CriteriaBuilder cb = dao.getCriteriaBuilder();
//		CriteriaQuery<DataImport> logCtQuery = cb.createQuery(DataImport.class);
//		Root<DataImport> logRoot = logCtQuery.from(DataImport.class);
		// userRoot.alias("u");
			List<Predicate> predicates = new ArrayList<Predicate>();
			Path<String> path = logRoot.<String>get("tableName");

			if (StringUtils.isNotBlank(queryParam.getTableName())) {
				predicates.add(cb.equal(path, queryParam.getTableName()));
			} else if (needFilterTable) {
				// 过滤无权看到的模板
				in(cb, predicates, path, tnames);
			}
			if (queryParam.getFromDate() != null) {
				predicates.add(cb.greaterThanOrEqualTo(logRoot.<Date>get("createTime"), queryParam.getFromDate()));
			}
			if (queryParam.getToDate() != null) {
				// todate 当天也要包括，所以加1天，小于第二天的0点
				predicates.add(cb.lessThan(logRoot.<Date>get("createTime"), DateUtils.addDays(queryParam.getToDate(), 1)));
			}
			if (queryParam.getState() != null) {
				predicates.add(cb.equal(logRoot.<DataImport.State>get("importState"), queryParam.getState()));
			}
			if (!SecurityUtils.getInstance().isLoginUserFromHeadquarter()) {
				LoginUser user = SecurityUtils.getInstance().getLoginUser();
				predicates.add(cb.equal(cb.upper(logRoot.<String>get("nodeCode")), user.getPrimaryOrg().getNodeCode()));
			}
			if (queryParam.getNodeCode() != null) {
				predicates.add(cb.equal(logRoot.<String>get("nodeCode"), queryParam.getNodeCode()));
			}
			if (queryParam.getDataDate() != null) {
				predicates.add(cb.equal(logRoot.<String>get("dataDate"), queryParam.getDataDate()));
			}
			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
		};
		if (StringUtils.isBlank(queryParam.getOrderBy())) {
			queryParam.setOrderBy("importState:ASC;createTime:DESC");
		}

		Page<DataImport> userPage = dataImportRepository.findAll(specification, queryParam.toPageRequest());
		PagedQueryResult<DataImport> result = new PagedQueryResult<>(userPage);
		for (DataImport di : result.getDatas()) {
			di.getActions().size();
		}
		return result;
	}

	<E> void in(CriteriaBuilder cb, List<Predicate> predicates, Path<E> path, Collection<E> values) {
		if ((values == null) || (values.size() == 0)) {
			return;
		}

		In<E> in = cb.in(path);
		Iterator<E> iterator = values.iterator();
		while (iterator.hasNext()) {
			in.value(iterator.next());
		}
		predicates.add(in);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.iisp.dataie.service.DataIEService#exportData(com.ibm.iisp.dataie.model.DataExportDef)
	 */
	@Override
	public String exportData(DataExportRequest dataExportReq) throws I18nAppException {
		// 如果客户端提供的信息不完整，则补充完整
		if (dataExportReq.getFilter() == null) {
			if (dataExportReq.getTemplateId() != null) {
				DataExportRequest der = this.getDataExportRequestByTemplate(dataExportReq.getTemplateId());
				dataExportReq.setFilter(der.getFilter());
				dataExportReq.setTableName(der.getTableName());
			} else if (dataExportReq.isUseTemplate()) {
				DataExportRequest der = this.getDataExportRequestByName(dataExportReq.getTableName(), dataExportReq.isUseTemplate());
				dataExportReq.setFilter(der.getFilter());
				dataExportReq.setTemplateId(der.getTemplateId());
			}
		}
		// 开始导出
		AbstractDataExporter exporter;
		if (dataExportReq.isUseTemplate()) {
			exporter = new CustomExcelDataExporter(dataExportReq, dao);
		} else {
			exporter = new CsvDataExporter(dataExportReq, dao);
		}
		String fname = exporter.init();
		exporter.preProcedure();
		exporter.doExport();
		exporter.finish();
		return fname;
	}

	@Override
	public List<DataIETable> getNodeImportTables() {
		TypedQuery<DataIETable> query = this.dao.createNamedQuery(DataImportNodeTable.QUERY_TABLE, DataIETable.class);
		return query.getResultList();
	}

	@Override
	public List<NodeImportState> getDataImportStateByTableAndDate(String tableCode, String dataDate) {
		DataImportNodeTable nt = this.dao.find(DataImportNodeTable.class, tableCode);
		// DataIETable die = dao.find(DataIETable.class, tableCode);
		StringBuilder sb = new StringBuilder(1024);
		sb.append("select o.code, o.name, count(ii.node_code) as data_cnt from (select distinct t0.").append(nt.getNodeColumn())
			.append(" from ").append(tableCode).append(" t0 where t0.DATA_DATE = '").append(dataDate).append("' ");
		// AbstractDataExporter.applyIncFilter(sb, die, dataDate);
		sb.append(") d1 join IISP_AUTH_ORG o on d1.").append(nt.getNodeColumn())
			.append(" = o.code left join IISP_DATA_IE_IMPORT ii on ii.node_code = o.code and II.IMPORT_STATE = 'IMPORTED' and II.TABLE_NAME = '")
			.append(tableCode).append("' AND II.DATA_DATE ='").append(dataDate).append("' group by o.code, o.name order by o.code");
		Query query = dao.createNativeQuery(sb.toString());
		@SuppressWarnings("unchecked")
		List<Object[]> states = query.getResultList();
		List<NodeImportState> nis = new ArrayList<>(states.size());
		for (Object[] st : states) {
			NodeImportState ns = new NodeImportState();
			ns.setTableCode(tableCode);
			ns.setNodeCode((String) st[0]);
			ns.setNodeName((String) st[1]);
			BigDecimal cnt = (BigDecimal) st[2];
			ns.setIsImported(cnt != null && cnt.intValue() > 0);
			nis.add(ns);
		}
		return nis;
	}
}
